package com.ultrapower.charts.delaunay
{
	import de.polygonal.ds.HashMap;
	import de.polygonal.ds.Iterator;
	
	/**
	 * Straightforward undirected graph implementation.
	 * Nodes are generic type N.
	 *
	 * @author Paul Chew
	 *
	 * Created November, December 2007.  For use in Delaunay/Voronoi code.
	 * 
	 * Translated to AS3 version by lwz7512, in Sep 2008.
	 *
	 */
	public class Graph
	{
		// Node -> adjacent nodes		
		public var theNeighbors:HashMap;
		
		
		public function Graph()
		{
			theNeighbors = new HashMap();			
		}

		/**
	     * Add a node.  If node is already in graph then no change.
	     * @param node the node to add
	     */
	    public function add (node:Object):void {
	        if (theNeighbors.containsKey(node)) return;
	        var arrset:ArraySet = new ArraySet(null);
	        theNeighbors.insert(node,arrset);
	     }
	
	    /**
	     * Add a link. If the link is already in graph then no change.
	     * @param nodeA one end of the link
	     * @param nodeB the other end of the link
	     * @throws NullPointerException if either endpoint is not in graph
	     */
	    public function addLink(nodeA:Object, nodeB:Object):void{
	    	
	    	try{
	    		ArraySet(theNeighbors.find(nodeA)).addItem(nodeB);
	        	ArraySet(theNeighbors.find(nodeB)).addItem(nodeA);
	    	}catch(e:Error){
	    		throw new Error("Null pointer error in finding node!");
	    	}
	        
	    }
	
	    /**
	     * Remove node and any links that use node. If node not in graph, nothing
	     * happens.
	     * @param node the node to remove.
	     */
	    public function removeNode(node:Object):void {
	        if (!theNeighbors.containsKey(node)) return;
	        var nodeNeighbors:ArraySet = ArraySet(theNeighbors.find(node));
	        var noedNeibIterator:Iterator = nodeNeighbors.iterator;
	        while(noedNeibIterator.hasNext()){
	        	var neighbor:Object =  noedNeibIterator.next();
	        	ArraySet(theNeighbors.find(neighbor)).removeItem(node);    // Remove "to" links
	        }	        	            	          
	        ArraySet(theNeighbors.find(node)).clear();                 // Remove "from" links
	        theNeighbors.remove(node);                      // Remove the node
	    }
	
	    /**
	     * Remove the specified link. If link not in graph, nothing happens.
	     * @param nodeA one end of the link
	     * @param nodeB the other end of the link
	     * @throws NullPointerException if either endpoint is not in graph
	     */
	    public function removeLink(nodeA:Object, nodeB:Object):void{
	    	try{
	    		ArraySet(theNeighbors.find(nodeA)).removeItem(nodeB);
	        	ArraySet(theNeighbors.find(nodeB)).removeItem(nodeA);
	    	}catch(e:Error){
	    		throw new Error("Null pointer error in finding node!");
	    	}
	        
	    }
	
	    /**
	     * Report all the neighbors of node.
	     * @param node the node
	     * @return the neighbors of node
	     * @throws NullPointerException if node does not appear in graph
	     */
	    public function getNeighbors (node:Object):ArraySet{
	    	var neighbors:ArraySet = theNeighbors.find(node) as ArraySet;
	        return  neighbors;
	    }
	
	    /**
	     * Returns an unmodifiable Set view of the nodes contained in this graph.
	     * The set is backed by the graph, so changes to the graph are reflected in
	     * the set.
	     * @return a Set view of the graph's node set
	     */
	    public function get nodeSet():Array{
	        return theNeighbors.getKeySet();;
	    }


	}//end of Graph;
}